function Laohuji(option) {
  let defaultOption = {
    el: null, // Dom/Selector 挂载的有固定宽高的容器 必填
    data: null, // Array 奖品数据 必填
    htmlMaker(data) { // Function 根据奖品数据生成HTML字符串
      return `<div>${JSON.stringify(data)}</div>`
    },
    curIdx: 0, // Number 当前显示的奖品索引号
    onEnd(data) { // 滚动结束回调
      console.log(data);
    },
  };
  option = { ...defaultOption, ...option };

  this.el = typeof option.el == 'string' ? document.querySelector(option.el) : option.el; // 挂载的容器dom对象
  this.data = option.data; // 奖品数据
  this.htmlMaker = option.htmlMaker; // 根据单条奖品数据生成HTML字符串
  this.curIdx = option.curIdx; // 当前显示的奖品对应的奖品数据的索引号
  this.box = document.createElement('div'); // 显示奖品的框框，溢出隐藏
  Object.assign(this.box.style, { // 设置奖品框框的css属性
    width: '100%',
    height: '100%',
    overflow: 'hidden',
  });
  this.wrap = document.createElement('div'); // 装载所有奖品的容器，该容器通过transform过渡动画来控制奖品的显示
  Object.assign(this.wrap.style, {
    width: '100%',
    height: '100%',
  });
  this.wrap.addEventListener('transitionend', () => { // 过渡动画结束回调
    this.running = false;
    option.onEnd(this.data[this.curIdx]);
  });
  this.box.appendChild(this.wrap);
  this.el.appendChild(this.box);
  this.height = this.wrap.offsetHeight;
  this.running = false; // 是否正在滚动
  this.blinkToCurIdx(); // 瞬间定位到当前索引位置
}

Laohuji.prototype.wrapInnerHtmlMaker = function (cycleTimes = 0) { // 根据动画的循环次数来打造奖品html字符串
  return Array(cycleTimes + 1).fill(
    this.data.map(
      (item, index) => (`
        <div style="width:100%;height:100%;">
          ${this.htmlMaker(item, index)}
        </div>
      `).replace(/\s*\n\s*/g, '')
    ).join('')
  ).join('');
};

Laohuji.prototype.blinkToCurIdx = function () { // 瞬间定位到当前索引位置
  this.wrap.innerHTML = this.wrapInnerHtmlMaker();
  Object.assign(this.wrap.style, {
    transition: '',
    transform: `translate3d(0,${-this.curIdx * this.height}px,0)`,
  });
};

Laohuji.prototype.animateTo = function (option) { // 动画滚动到目标位置
  if (this.running) return;
  this.running = true;
  let def = {
    cycleTimes: 3, // 循环次数
    duration: 10000, // 持续时间ms
    targetIdx: Math.floor(Math.random() * this.data.length), // 目标位置
    ease: 'cubic-bezier(0.88, 0.05, 0.07, 0.96)', // css缓动效果
  };
  option = { ...def, ...option };
  this.curIdx = option.targetIdx;
  this.wrap.innerHTML = this.wrapInnerHtmlMaker(option.cycleTimes);
  Object.assign(this.wrap.style, {
    transition: `transform ${option.duration}ms ${option.ease}`,
    transform: `translate3d(0,${-(this.curIdx + this.data.length * option.cycleTimes) * this.height}px,0)`,
  });
};

Laohuji.prototype.start = function (option) { // 开奖
  if (this.running) return;
  this.blinkToCurIdx();
  setTimeout(() => this.animateTo(option), 0);
};